/*!
 *  \file	test-fft2D-proc1.cpp
 *  \brief	Main per testare se la FFT2D procedura 1 coincide con quella di ImageJ
 *
 * Questo programma testa se la FFT2D generata con la procedura 1 dal segnale passato
 * da commandline coincide con la FFT2D generata con ImageJ
 *
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author	Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 *
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <iostream>
#include <vector>
#include <complex>
#include "SimpleMatrix.cpp"
#include "SimpleRawImage.cpp"
#include "Fft2D.cpp"

/* Image Type: same meaning as ImageJ but in bytes instead of bits */
#ifdef IMAGE_TYPE
# undef IMAGE_TYPE
#endif

#define IMAGE_TYPE	8

/* Some funny preprocessor things ... :> */
#if SIZEOF_FLOAT == IMAGE_TYPE
# define	TTYPE		float
#elif SIZEOF_DOUBLE == IMAGE_TYPE
# define	TTYPE		double
#elif SIZEOF_LONGDOUBLE == IMAGE_TYPE
# define	TTYPE		long double
#else
# error "The impossible was happened; your implementation does not have any viable floating point"
#endif

using namespace std;

void
shift( SimpleMatrix< complex< TTYPE > >& image )
{
  complex< TTYPE > alfa, beta;
  unsigned int halfRows = image.getRows() / 2;
  unsigned int halfCols = image.getCols() / 2;
  
  for( unsigned int i = 0; i < halfRows; ++i )
  {
    for( unsigned int j = 0; j < halfCols; ++j )
    {
      alfa = image( i, j);
      beta = image( i + halfRows, j + halfCols );
      
      image( i, j ) = beta;
      image( i + halfRows, j + halfCols ) = alfa;
    }
  }
  
  for( unsigned int i = 0; i < halfRows; ++i )
  {
    for( unsigned int j = halfCols; j < image.getCols(); ++j )
    {
      alfa = image( i + halfRows, j - halfCols );
      beta = image( i, j );
      
      image( i, j ) = alfa;
      image( i + halfRows, j - halfCols ) = beta;
    }
  }
}

void
unshift( SimpleMatrix< complex< TTYPE > >& image )
{
  complex< TTYPE > alfa, beta;
  unsigned int halfRows = image.getRows() / 2;
  unsigned int halfCols = image.getCols() / 2;
  
  for( unsigned int i = 0; i < halfRows; ++i )
  {
    for( unsigned int j = halfCols; j < image.getCols(); ++j )
    {
      alfa = image( i + halfRows, j - halfCols );
      beta = image( i, j );
      
      image( i, j ) = alfa;
      image( i + halfRows, j - halfCols ) = beta;
    }
  }
  
  for( unsigned int i = 0; i < halfRows; ++i )
  {
    for( unsigned int j = 0; j < halfCols; ++j )
    {
      alfa = image( i, j);
      beta = image( i + halfRows, j + halfCols );
      
      image( i, j ) = beta;
      image( i + halfRows, j + halfCols ) = alfa;
    }
  }
}


int
main(void)
{
  SimpleRawImage< TTYPE > input( IMAGE_SIZE, IMAGE_SIZE );
  SimpleRawImage< TTYPE > output( IMAGE_SIZE, IMAGE_SIZE );
  SimpleRawImage< TTYPE > original( IMAGE_SIZE, IMAGE_SIZE );
  
  input.importFromFile( "lena.raw" );
  
  Fft2D< TTYPE > fft2d( input );
  
  // andata ...
  fft2d.compute( );
  fft2d.applyOperator( shift );
  fft2d.outMagnitude( Fft2D< TTYPE >::OP_LOGARITHMIC,
		      output );

  // ... e ritorno
  fft2d.applyOperator( unshift );
  fft2d.invert( );
  fft2d.outMagnitude( 0, original );
  
  output.exportToFile( "test-fft2D-proc1.raw" );
  original.exportToFile( "test-fft2D-INV-proc1.raw" );
  return 0;
}
